package com.yt.order.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;

//计算距离
public class DistanceUtils {
    // 地球半径(公里)
    private static final BigDecimal EARTH_RADIUS = new BigDecimal("6371.0");
    // 弧度转换系数(π/180)
    private static final BigDecimal RADIAN_COEFFICIENT = new BigDecimal(Math.PI).divide(new BigDecimal("180"), 10, RoundingMode.HALF_UP);

    //把地址转换为经纬度
    public static TencentMapGeocoder.GeocoderResponse.Location getDistance(String address, String region) {
        TencentMapGeocoder.GeocoderResponse.Location location=TencentMapGeocoder.addressToLatLng(address,region);
        return location;
    }
    /**
     * 计算两点经纬度距离(单位：KM)
     * @param lat1 纬度1
     * @param lon1 经度1
     * @param lat2 纬度2
     * @param lon2 经度2
     * @return 距离（保留6位小数）
     */
    public static BigDecimal calculateDistance(
            String address, String region,
            BigDecimal lat2, BigDecimal lon2) {
        TencentMapGeocoder.GeocoderResponse.Location location = getDistance(address, region);
        BigDecimal lat1 = location.getLat(); // 获取纬度
        BigDecimal lon1 = location.getLng(); // 获取经度
        System.out.println("lat1="+lat1+",lon1="+lon1);
        // 角度转弧度
        BigDecimal radLat1 = lat1.multiply(RADIAN_COEFFICIENT);
        BigDecimal radLon1 = lon1.multiply(RADIAN_COEFFICIENT);
        BigDecimal radLat2 = lat2.multiply(RADIAN_COEFFICIENT);
        BigDecimal radLon2 = lon2.multiply(RADIAN_COEFFICIENT);

        // 经纬度差值
        BigDecimal deltaLat = radLat2.subtract(radLat1);
        BigDecimal deltaLon = radLon2.subtract(radLon1);

        // Haversine公式计算
        BigDecimal a = sin(deltaLat.divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP)).pow(2)
                .add(cos(radLat1).multiply(cos(radLat2))
                        .multiply(sin(deltaLon.divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP)).pow(2)));

        BigDecimal c = new BigDecimal("2").multiply(atan2(sqrt(a), sqrt(BigDecimal.ONE.subtract(a))));

        // 计算距离并保留6位小数
        return EARTH_RADIUS.multiply(c).setScale(6, RoundingMode.HALF_UP);
    }

    // 角度转正弦值（基于Math.sin简化实现）
    private static BigDecimal sin(BigDecimal value) {
        return new BigDecimal(Math.sin(value.doubleValue()), new java.math.MathContext(10));
    }

    // 角度转余弦值
    private static BigDecimal cos(BigDecimal value) {
        return new BigDecimal(Math.cos(value.doubleValue()), new java.math.MathContext(10));
    }

    // 平方根计算（简化迭代逻辑）
    private static BigDecimal sqrt(BigDecimal value) {
        // 1. 处理负数场景（保留原逻辑）
        if (value.compareTo(BigDecimal.ZERO) < 0) {
            throw new ArithmeticException("平方根不能为负数，当前值：" + value);
        }
        // 2. 处理value=0的场景（直接返回0，避免迭代）
        if (value.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        // 3. 优化初始值：避免guess过小（参考Math.sqrt的初始值策略，提升迭代效率）
        BigDecimal guess;
        if (value.compareTo(BigDecimal.ONE) >= 0) {
            // 当value≥1时，初始值设为value/2
            guess = value.divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP);
        } else {
            // 当0<value<1时，初始值设为value（或2*value，避免过小）
            guess = new BigDecimal("2").multiply(value);
        }
        // 4. 迭代计算（保留原迭代次数，确保精度）
        for (int i = 0; i < 20; i++) {
            guess = guess.add(value.divide(guess, 10, RoundingMode.HALF_UP))
                    .divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP);
        }
        return guess;
    }

    // 反正切计算
    private static BigDecimal atan2(BigDecimal y, BigDecimal x) {
        return new BigDecimal(Math.atan2(y.doubleValue(), x.doubleValue()), new java.math.MathContext(10));
    }
}